﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VietThinks.Contract;
using AutoMapper;
using VietThinks.Model;

namespace VietThinks.Service
{
    /// <summary>
    /// Fluent interface to Entity-Dto conversion
    /// </summary>
    internal static partial class Convert
    {
        public static EntityConverter<TEntity> Entity<TEntity>(TEntity entity)
            where TEntity : DomainEntity
        {
            return new EntityConverter<TEntity>(entity);
        }

        public static ValueConverter<TValue> Value<TValue>(TValue value)
        //where TValue : IValueObject
        {
            return new ValueConverter<TValue>(value);
        }

        public static DtoConverter<TDto> Dto<TDto>(TDto dto)
            where TDto : IdentifiableDto
        {
            return new DtoConverter<TDto>(dto);
        }
    }

    internal class EntityConverter<TEntity>
        where TEntity : DomainEntity
    {
        public EntityConverter(TEntity entity)
        {
            this.entity = entity;
        }

        private readonly TEntity entity;

        public TDto ToDto<TDto>()
        {
            return Mapper.Map<TEntity, TDto>(this.entity);
        }
    }

    internal class ValueConverter<TValue>
    //where TValue : IValueObject
    {
        public ValueConverter(TValue value)
        {
            this.value = value;
        }

        private readonly TValue value;

        public TDto ToDto<TDto>()
        {
            return Mapper.Map<TValue, TDto>(this.value);
        }
    }

    internal class DtoConverter<TDto>
        where TDto : IdentifiableDto
    {
        public DtoConverter(TDto dto)
        {
            this.dto = dto;
        }

        private readonly TDto dto;

        public TEntity ToEntity<TEntity>(DomainRepository repository)
            where TEntity : DomainEntity
        {
            using (RepositoryScope.Share(repository))
            {
                var entity = this.dto.Id == 0 ? null : repository.Get<TEntity>(this.dto.Id);

                if (!typeof(IReadOnly).IsAssignableFrom(typeof(TEntity)))
                {
                    if (entity != null)
                    {
                        entity = Mapper.Map(this.dto, entity);
                    }
                    else
                    {
                        entity = Mapper.Map<TDto, TEntity>(this.dto);
                    }
                }

                return entity;
            }
        }
    }
}
